home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / cpuaccel.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  3.6 KB  |  156 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include <wtypes.h>
  19. #include <winnt.h>
  20. #include "cpuaccel.h"
  21.  
  22. static long g_lCPUExtensionsEnabled;
  23. static long g_lCPUExtensionsAvailable;
  24.  
  25. extern "C" {
  26.     bool FPU_enabled, MMX_enabled, ISSE_enabled;
  27. };
  28.  
  29. // This is ridiculous.
  30.  
  31. static long CPUCheckForSSESupport() {
  32.     __try {
  33. //        __asm andps xmm0,xmm0
  34.  
  35.         __asm _emit 0x0f
  36.         __asm _emit 0x54
  37.         __asm _emit 0xc0
  38.  
  39.     } __except(EXCEPTION_EXECUTE_HANDLER) {
  40.         if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION)
  41.             g_lCPUExtensionsAvailable &= ~(CPUF_SUPPORTS_SSE|CPUF_SUPPORTS_SSE2);
  42.     }
  43.  
  44.     return g_lCPUExtensionsAvailable;
  45. }
  46.  
  47. long __declspec(naked) CPUCheckForExtensions() {
  48.     __asm {
  49.         push    ebp
  50.         push    edi
  51.         push    esi
  52.         push    ebx
  53.  
  54.         xor        ebp,ebp            ;cpu flags - if we don't have CPUID, we probably
  55.                                 ;won't want to try FPU optimizations.
  56.  
  57.         ;check for CPUID.
  58.  
  59.         pushfd                    ;flags -> EAX
  60.         pop        eax
  61.         or        eax,00200000h    ;set the ID bit
  62.         push    eax                ;EAX -> flags
  63.         popfd
  64.         pushfd                    ;flags -> EAX
  65.         pop        eax
  66.         and        eax,00200000h    ;ID bit set?
  67.         jz        done            ;nope...
  68.  
  69.         ;CPUID exists, check for features register.
  70.  
  71.         mov        ebp,00000003h
  72.         xor        eax,eax
  73.         cpuid
  74.         or        eax,eax
  75.         jz        done            ;no features register?!?
  76.  
  77.         ;features register exists, look for MMX, SSE, SSE2.
  78.  
  79.         mov        eax,1
  80.         cpuid
  81.         mov        ebx,edx
  82.         and        ebx,00800000h    ;MMX is bit 23
  83.         shr        ebx,21
  84.         or        ebp,ebx            ;set bit 2 if MMX exists
  85.  
  86.         mov        ebx,edx
  87.         and        edx,02000000h    ;SSE is bit 25
  88.         shr        edx,25
  89.         neg        edx
  90.         and        edx,00000018h    ;set bits 3 and 4 if SSE exists
  91.         or        ebp,edx
  92.  
  93.         and        ebx,04000000h    ;SSE2 is bit 26
  94.         shr        ebx,21
  95.         and        ebx,00000020h    ;set bit 5
  96.         or        ebp,ebx
  97.  
  98.         ;check for vendor feature register (K6/Athlon).
  99.  
  100.         mov        eax,80000000h
  101.         cpuid
  102.         mov        ecx,80000001h
  103.         cmp        eax,ecx
  104.         jb        done
  105.  
  106.         ;vendor feature register exists, look for 3DNow! and Athlon extensions
  107.  
  108.         mov        eax,ecx
  109.         cpuid
  110.  
  111.         mov        eax,edx
  112.         and        edx,80000000h    ;3DNow! is bit 31
  113.         shr        edx,25
  114.         or        ebp,edx            ;set bit 6
  115.  
  116.         mov        edx,eax
  117.         and        eax,40000000h    ;3DNow!2 is bit 30
  118.         shr        eax,23
  119.         or        ebp,eax            ;set bit 7
  120.  
  121.         and        edx,00400000h    ;AMD MMX extensions (integer SSE) is bit 22
  122.         shr        edx,19
  123.         or        ebp,edx
  124.  
  125. done:
  126.         mov        eax,ebp
  127.         mov        g_lCPUExtensionsAvailable, ebp
  128.  
  129.         ;Full SSE and SSE-2 require OS support for the xmm* registers.
  130.  
  131.         test    eax,00000030h
  132.         jz        nocheck
  133.         call    CPUCheckForSSESupport
  134. nocheck:
  135.         pop        ebx
  136.         pop        esi
  137.         pop        edi
  138.         pop        ebp
  139.         ret
  140.     }
  141. }
  142.  
  143. long CPUEnableExtensions(long lEnableFlags) {
  144.     g_lCPUExtensionsEnabled = lEnableFlags;
  145.  
  146.     MMX_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_MMX);
  147.     FPU_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_FPU);
  148.     ISSE_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_INTEGER_SSE);
  149.  
  150.     return g_lCPUExtensionsEnabled;
  151. }
  152.  
  153. long CPUGetEnabledExtensions() {
  154.     return g_lCPUExtensionsEnabled;
  155. }
  156.